package com.cetcs.kmga.dataManager.dao.hbase.impl;

import com.cetcs.kmga.common.HBaseUtil;
import com.cetcs.kmga.common.Page;
import com.cetcs.kmga.dataManager.dao.hbase.HBaseQueryConf;
import com.cetcs.kmga.dataManager.dao.hbase.ILogManagerBaseDao;
import com.cetcs.kmga.dataManager.dao.hbase.LogOuterQuery;
import com.cetcs.kmga.dataManager.dao.hbase.LogRowKeyQuery;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Repository;
import org.springframework.util.StringUtils;

import java.util.Iterator;
import java.util.List;
import java.util.Map;

/**
 *
 * 封装的habse 日志查询dao实现类
 *
 * @author yyangs
 * @version V1.0 创建时间：2017-09-06 10:18
 *          Copyright 2017 by CETC
 */
@Repository
public class LogManagerBaseDaoImpl implements ILogManagerBaseDao {

    private static Logger LOG = LoggerFactory.getLogger(LogManagerBaseDaoImpl.class);


    /**
     * 作为rowKey查询的名字
     */
    private static final String ROW_KEY_NAME = "ID";

    private final static String ROWKEY_SUFFIX_ANALY = "0000000000000000000000";


    /**
     * 查询清洗过后的日志不带分页的查询
     *
     * @param indexName  数据库名
     * @param tbName     表名
     * @param columnArr
     * @param rowKey     组装rowKey查询条件
     * @param outers     普通的查询条件
     * @param sortFields 排序规则
     * @return
     * @throws Exception
     */
    @Override
    public List<Map<String, Object>> findCleanLogRecords(String indexName, String tbName, List<String> columnArr, LogRowKeyQuery rowKey, List<LogOuterQuery> outers, Map<String, Integer> sortFields) throws Exception {
        String bufferOuterSql = joinQuerySql(indexName, tbName, columnArr, rowKey, outers, sortFields);
        return HBaseUtil.getInstance().queryListNoQueryCondition(bufferOuterSql);
    }


    /**
     * 拼接查询条件
     *
     * @param tbName     表名
     * @param columnArr  字段
     * @param rowKey     组装rowKey
     * @param outers     外部查询条件
     * @param sortFields 排序字段
     * @return
     */
    private String joinQuerySql(String indexName, String tbName, List<String> columnArr, LogRowKeyQuery rowKey, List<LogOuterQuery> outers, Map<String, Integer> sortFields) throws Exception {
        if (StringUtils.isEmpty(tbName)) {
            throw new RuntimeException("tbName is null!");
        }
        if (rowKey == null) {
            throw new RuntimeException("row key  is null!");
        }
        //判断rowKey的时间是否为空
        if (StringUtils.isEmpty(rowKey.getStartTime()) || StringUtils.isEmpty(rowKey.getEndTime())) {
            throw new RuntimeException("row key time is null!");
        }
        //判断rowKey时间长度
        if (rowKey.getStartTime().length() != 14 || rowKey.getEndTime().length() != 14) {
            throw new RuntimeException("row key time length is error!");
        }
        String rowKeyProfoxStart = joinRowKey(rowKey.getStartTime(), rowKey.getOtherKeys());
        long endTimeL = Long.valueOf(rowKey.getEndTime()) + 1;
        String rowKeyProfoxEnd = joinRowKey(String.valueOf(endTimeL), rowKey.getOtherKeys());
        //开始组装内层查询
        StringBuffer columnBuffer = new StringBuffer();
        if (columnArr != null && columnArr.size() > 0) {
            for (int i = 0; i < columnArr.size(); i++) {
                if (i != 0) {
                    columnBuffer.append(" , ");
                }
                columnBuffer.append(columnArr.get(i));
            }
        } else {
            columnBuffer.append(" * ");
        }
        //内层sql
        StringBuffer bufferInnerSql = new StringBuffer();
        bufferInnerSql.append(" select ").append(columnBuffer.toString()).append(" from ").
                append(indexName).append(".").append(tbName).append(" where ").append(ROW_KEY_NAME).append(" >= ").append(rowKeyProfoxStart).append(" and ")
                .append(ROW_KEY_NAME).append(" < ").append(rowKeyProfoxEnd);
        LOG.info(" inner sql:" + bufferInnerSql.toString());
        //组装外层sql，普通查询条件
        StringBuffer bufferOuterSql = new StringBuffer();
        bufferOuterSql.append(" select  * from  ( ").append(bufferInnerSql).append(" ) inner ");
        //===start 不带条件的拼装，开始拼接查询条件
        if (outers != null && outers.size() > 0) {
            bufferOuterSql.append(" WHERE ");
            int ret = 0;
            for (int i = 0; i < outers.size(); i++) {
                LogOuterQuery outer = outers.get(i);
                if (ret != 0) {
                    bufferOuterSql.append(" and ");
                }
                //根据条件类型组装查询条件参数
                switch (outer.getQueryType()) {
                    //= 查询
                    case HBaseQueryConf.QUERY_TYPE_EQUAL:
                        bufferOuterSql.append(" ").append(outer.getColumnName()).append(" = '").append(outer.getKeywords()).append("'");
                        break;
                    // in 查询
                    case HBaseQueryConf.QURYY_TYPE_IN:
                        if (outer.getKeywords() instanceof List) {
                            List<Object> arrList = (List<Object>) outer.getKeywords();
                            String inStr = "";
                            for (int j = 0; j < arrList.size(); j++) {
                                if (j != 0) {
                                    inStr += ",";
                                }
                                inStr += arrList.get(j);
                            }
                            bufferOuterSql.append(" ").append(outer.getColumnName()).append(" in( ").append(inStr).append(" )");
                        } else if (outer.getKeywords() instanceof String) {
                            bufferOuterSql.append(" ").append(outer.getColumnName()).append(" in( ").append(outer.getKeywords()).append(" )");
                        }
                        break;
                    // like 查询
                    case HBaseQueryConf.QUERY_TYPE_LIKE:
                        bufferOuterSql.append(" ").append(outer.getColumnName()).append(" like '%").append(outer.getKeywords()).append("%'");
                        break;
                    //自定义语句片段
                    case HBaseQueryConf.QURYY_TYPE_DEFINED:
                        bufferOuterSql.append(" ").append(outer.getKeywords());
                        break;
                }
            }
        }
        //===== end 查询条件组装完成
        if (sortFields != null && sortFields.size() > 0) {
            int orderByRet = 0;
            bufferOuterSql.append(" ORDER BY ");
            Iterator<Map.Entry<String, Integer>> entryOrderBy = sortFields.entrySet().iterator();
            while (entryOrderBy.hasNext()) {
                Map.Entry<String, Integer> entry = entryOrderBy.next();
                String column = entry.getKey();
                int orderType = entry.getValue();
                if (orderByRet == 0) {
                    if (orderType == 0) {
                        bufferOuterSql.append(" ").append(column.toUpperCase()).append(" DESC ");
                    } else {
                        bufferOuterSql.append(" ").append(column.toUpperCase()).append(" ASC ");
                    }
                } else {
                    if (orderType == 0) {
                        bufferOuterSql.append(" , ").append(column.toUpperCase()).append(" DESC ");
                    } else {
                        bufferOuterSql.append(" , ").append(column.toUpperCase()).append(" ASC ");
                    }
                }
                orderByRet++;
            }
        }
        LOG.info(" outer sql:" + bufferOuterSql.toString());
        return bufferOuterSql.toString();

    }


    /**
     * 拼接rowKey的方法
     *
     * @param time      时间戳
     * @param otherKeys 其他rowKey字段
     * @return
     */
    private String joinRowKey(String time, List<String> otherKeys) {
        StringBuffer rowKeyBuffer = new StringBuffer();
        if (otherKeys != null && otherKeys.size() > 0) {
            for (String keyStr : otherKeys) {
                rowKeyBuffer.append(keyStr);
            }
        }
        rowKeyBuffer.append(time).append(ROWKEY_SUFFIX_ANALY);
        return rowKeyBuffer.toString();
    }

    /**
     * 带分页的查询，返回公共的分页对象
     *
     * @param indexName  数据库名
     * @param tbName     表名
     * @param columnArr  查询字段
     * @param rowKey     组装rowKey查询条件
     * @param outers     普通的查询条件
     * @param sortFields 排序规则
     * @param page       当前页
     * @param pageSize   每页多少条
     * @return
     * @throws Exception
     */
    @Override
    public Page findCleanLogRecordsByPageCondition(String indexName, String tbName, List<String> columnArr, LogRowKeyQuery rowKey, List<LogOuterQuery> outers, Map<String, Integer> sortFields, int page, int pageSize) throws Exception {
        String bufferOuterSql = joinQuerySql(indexName, tbName, columnArr, rowKey, outers, sortFields);
        return HBaseUtil.getInstance().queryListByPageNoQueryCondition(bufferOuterSql, page, pageSize);
    }
}
